# TODO: 神经网络基本实现原理
# DATE: 2022/3/18
# AUTHOR: Cheng Ze WUST

import numpy as np

#矩阵乘法
a=np.array([[1,2],[3,4],[5,6]])
print(a.shape)
b=np.array([[5,6,7],[7,8,9]])
print(b.shape)

c=np.dot(a,b)
print(c)


#region 三层神经网络实现原理
X=np.array([1.0,0.5])	#输入（两个输入一个偏置）
W1=np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
B1=np.array([0.1,0.2,0.3])	#第一层有三个神经元(B为偏置)

A1=np.dot(X,W1)+B1	#A=XW+B 	A(a1,a2,a3)
print("A1",A1)

def sigmoid(x):	#sigmoid函数
	return 1/(1+np.exp(-x))

Z1=sigmoid(A1)	#第一层神经元的输出
print(Z1)

#处理第二层神经元（行：输入数量；列：神经元数量）
W2=np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
B2=np.array([0.1,0.2])
A2=np.dot(Z1,W2)+B2
print("A2",A2)
Z2=sigmoid(A2)
print(Z2)

#处理输出层
W3=np.array([[0.1,0.3],[0.2,0.4]])
B3=np.array([0.1,0.2])
A3=np.dot(Z2,W3)+B3
Y=sigmoid(A3)
print("Y",Y)
#endregion


#region 三层神经网络完整实现
def init_network():
	network={}
	network['W1']=np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
	network['b1']=np.array([0.1,0.2,0.3])
	network['W2']=np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
	network['b2']=np.array([0.1,0.2])
	network['W3']=np.array([[0.1,0.3],[0.2,0.4]])
	network['b3']=np.array([0.1,0.2])
	return network
def tanh(x):	#Tanh函数
	return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))
def forward(network,X,level,activation):
	W=network['W'+str(level)]
	b=network['b'+str(level)]
	a=np.dot(X,W)+b
	z=activation(a)
	return z
network=init_network()
X=np.array([1.0,0.5])
for i in range(1,4):
	X=forward(network,X,i,tanh)
print(X)
#endregion


#region softmax函数
#神经网络主要用途：回归、分类
#回归：恒等函数（输入信号a与输出信号y相同）
#分类：softmax函数
def softmax(a):
	exp_a=np.exp(a)
	sum_exp_a=np.sum(exp_a)
	y=exp_a/sum_exp_a
	return y
a=np.array([0.3,2.9,4.1])
print(softmax(a))	#取最大比例为输出

#改进的softmax函数
def softmax_Pro(a):
	c=np.max(a)
	exp_a=np.exp(a-c)
	sum_exp_a=np.sum(exp_a)
	y=exp_a/sum_exp_a
	return y
a=np.array([0.3,2.9,4.1])
print(softmax_Pro(a))
#endregion


